% Use topsConditions to traverse random stimulus conditions
clear classes
clc
dotsTheDrawablesManager.reset('clientMode', false, 'serverMode', false);

% create a stimulus object, a random dots kinetogram
dm = dotsTheDrawablesManager.theObject;
stimulus = dm.newObject('dotsDrawableDotKinetogram');
stimulus.y = -3;

% create a label for the stimulus
label = dm.newObject('dotsDrawableText');
label.string = 'matching color';
label.y = 3;

% tell the draw manager to draw 'all' objects at once
dm.activateGroup('all');

%% create sets of values for several simulus properties
conditions = topsConditions;
conditions.addParameter('color', {[255 0 0], [0 128 0] [255 255 255]});
conditions.addParameter('coherence', {0, 100});
conditions.addParameter('angle', {0, 180});

%% assign the parameters to properties of the stimulus and label
%   each parameter can have multple assignments
%   the parameter assignment target don't have to have the same name
conditions.addAssignment('color', stimulus, '.', 'color');
conditions.addAssignment('color', label, '.', 'color');
conditions.addAssignment('coherence', stimulus, '.', 'coherence');
conditions.addAssignment('angle', stimulus, '.', 'direction');

% traverse parameter combinations bu shuffling them
% after setting new combinations, show off the graphics
conditions.setPickingMethod('shuffled');
conditions.name = 'pick conditions';

%% package up some functions to animate the stimulus
animator = topsCallList;
animator.addCall({@mayDrawNextFrame, dm, true});
animator.addCall({@runForDuration, dm, 1});
animator.addCall({@mayDrawNextFrame, dm, false});
animator.name = 'animate';

%% use a "tree node" to organize a mini-experiment
%   most steps below build up a "recipe" for the experiment
%   the final step executes the experiment with run()
runTree = topsTreeNode;
runTree.name = 'mini experiment:'

% first of all, open a drawing window
runTree.startFevalable = {@openScreenWindow, dm};

% then try to run() the conditions object and animator infinity times...
% ...but the conditions object will tell its "caller", the runTree, to stop
% running after traversing the finite number of conditions.
runTree.addChild(conditions);
runTree.addChild(animator);
runTree.iterations = inf;

% finally, close the drawing window
runTree.finishFevalable = {@closeScreenWindow, dm};

%% Run the mini-experiment
runTree.run;

%% Overview of the mini-experiment
%runTree.gui;